package com.itlong.cloud.wechat.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.type.TypeReference;
import com.itlong.cloud.POJO.DTO.common.WeChatVisitorMsgDTO;
import com.itlong.cloud.PlatformConstants;
import com.itlong.cloud.constants.RedisConstant;
import com.itlong.cloud.service.RedisService;
import com.itlong.cloud.utils.network.http.HttpProtocolUtil;
import com.itlong.cloud.utils.node.JsonUtil;
import com.itlong.cloud.wechat.dao.IWeChatDao;
import com.itlong.cloud.wechat.service.IWeChatTemplateMsgService;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * <desc>
 *      微信模板消息服务层接口实现类
 * </desc>
 *
 * @createDate 2019/04/26
 */
@Service
@RefreshScope
public class WeChatTemplateMsgServiceImpl implements IWeChatTemplateMsgService {

    private static final Logger LOG = LoggerFactory.getLogger(WeChatTemplateMsgServiceImpl.class);

    @Value("${" + PlatformConstants.MINI_PROGRAM_APPID + "}")
    public String MINI_PROGRAM_APPID;

    @Value("${" + PlatformConstants.WECHAT_OFFICIAL_REQUEST_URL + "}")
    public String WECHAT_OFFICIAL_REQUEST_URL;

    @Value("${" + PlatformConstants.WECHAT_OFFICIAL_APPID + "}")
    public String WECHAT_OFFICIAL_APPID;

    @Value("${" + PlatformConstants.WECHAT_OFFICIAL_SECRET + "}")
    public String WECHAT_OFFICIAL_SECRET;

    @Value("${" + PlatformConstants.VISITOR_TEMPLATE_ID + "}")
    public String VISITOR_TEMPLATE_ID;

    @Value("${" + PlatformConstants.OWNER_TEMPLATE_ID + "}")
    public String OWNER_TEMPLATE_ID;

    @Autowired
    private RedisService redisService;

    @Autowired
    private IWeChatDao iWeChatDao;

    private static ExecutorService importAddressFixedThreadPool = Executors.newFixedThreadPool(10); // 同步数据线程池

    /**
     * <desc>
     *      发送微信公众号模板消息，目前业务为写字楼访客预约相关
     * </desc>
     *
     * @param weChatVisitorMsgDTO 访客预约流程发送微信公众号模板消息DTO
     * @author wangzhi
     * @createDate 2019/04/26
     */
    @Override
    public void sendWeChatTemplateMsg(WeChatVisitorMsgDTO weChatVisitorMsgDTO) throws Exception {
        importAddressFixedThreadPool.execute(() -> {
            try {
                this.sendWeChatTemplateMsgExecute(weChatVisitorMsgDTO);
            } catch (Exception e) {
                LOG.info("发送模板消息执行失败：" + weChatVisitorMsgDTO, e);
            }
        });
    }

    /**
     * <desc>
     *      执行发送微信公众号模板消息，目前业务为写字楼访客预约相关
     * </desc>
     *
     * @param weChatVisitorMsgDTO 访客预约流程发送微信公众号模板消息DTO
     * @author wangzhi
     * @createDate 2019/04/26
     */
    private void sendWeChatTemplateMsgExecute(WeChatVisitorMsgDTO weChatVisitorMsgDTO) throws Exception {
        // msgStatus 消息状态 0被访人或物业拒绝，1访客未审批，2业主未审批，3业主审批通过，不要物业，4业主审批通过，要物业，5物业审批通过访客，6物业审批通过被访人
        // 请求参数集，访客和业主
        Map<String,Object> paramsVisitor = new HashMap<>();
        Map<String,Object> paramsOwner = new HashMap<>();
        // 先获取access_token
        String accessToken = redisService.get(RedisConstant.WECHAT_OFFICIAL_ACCESS_TOKEN);
        if (StringUtils.isBlank(accessToken)) {
            // 缓存中已经过期了，重新获取
            String requestUrl = "https://api.weixin.qq.com/cgi-bin/token"+"?appid="+WECHAT_OFFICIAL_APPID+"&secret="+WECHAT_OFFICIAL_SECRET+"&grant_type=client_credential";
            JSONObject jsonObject = HttpProtocolUtil.httpsRequest(requestUrl, "GET", null);
            if (jsonObject != null) {
                accessToken = jsonObject.getString("access_token");
                if(StringUtils.isNotBlank(accessToken)){
                    redisService.set(RedisConstant.WECHAT_OFFICIAL_ACCESS_TOKEN,RedisConstant.WECHAT_OFFICIAL_TIME,accessToken);
                }
            }
        }
        String remoteUrl = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" + accessToken;
        // 获取访客预约相关发送模板消息所需信息
        Map<String, Object> visitorPassInfoMap = iWeChatDao.getAppVisitorPassCodeByPassId(weChatVisitorMsgDTO.getPassId());
        if (visitorPassInfoMap == null) {
            return;
        }
        LOG.info("发送模板消息第一个查询数据visitorPassInfoMap：" + visitorPassInfoMap);
        // 获取信息接收者的openId
        String openIdVisitor = iWeChatDao.getOfficialOpenIdByUserId(visitorPassInfoMap.get("userIdVisitor").toString());
        LOG.info("数据库查询访客openId：" + openIdVisitor);
        paramsVisitor.put("touser",openIdVisitor);
        String openIdOwner = iWeChatDao.getOfficialOpenIdByUserId(visitorPassInfoMap.get("userIdOwner").toString());
        LOG.info("数据库查询业主openId：" + openIdOwner);
        paramsOwner.put("touser",openIdOwner);
        // 模板ID，分业务从已创建中选择
//        paramsVisitor.put("template_id","-IB2Hjf1emcUUUWxP-1gtkcfFREojbhcG1esY2ve_rA");
//        paramsOwner.put("template_id","sNZo23JqzJQWsffIMbsgTKVIdxglyupQMKQEhCBbanU");
        paramsVisitor.put("template_id",VISITOR_TEMPLATE_ID);
        paramsOwner.put("template_id",OWNER_TEMPLATE_ID);
        // 模板跳转链接暂无，跳转到小程序
        Map<String,Object> miniprogramVisitor = new HashMap<>();
        Map<String,Object> miniprogramOwner = new HashMap<>();
        Map<String,Object> keyword1Visitor = new HashMap<>();
        Map<String,Object> keyword1Owner = new HashMap<>();
        Map<String,Object> keyword4Visitor = new HashMap<>();
        Map<String,Object> keyword4Owner = new HashMap<>();
        Map<String,Object> dataVisitor = new HashMap<>();
        Map<String,Object> dataOwner = new HashMap<>();
        // 模板数据填充
        Map<String,Object> keyword2 = new HashMap<>();
        keyword2.put("value",visitorPassInfoMap.get("orderTime"));  // 预约时间
        keyword2.put("color","#000000");
        dataVisitor.put("keyword2",keyword2);
        dataOwner.put("keyword2",keyword2);
        Map<String,Object> keyword3 = new HashMap<>();
        keyword3.put("value",visitorPassInfoMap.get("address"));    // 预约地点
        keyword3.put("color","#000000");
        dataVisitor.put("keyword3",keyword3);
        dataOwner.put("keyword3",keyword3);
        Map<String,Object> keyword5 = new HashMap<>();
        keyword5.put("value",visitorPassInfoMap.get("visitorCause"));   // 被访事由
        keyword5.put("color","#000000");
        dataVisitor.put("keyword5",keyword5);
        dataOwner.put("keyword5",keyword5);
        switch (weChatVisitorMsgDTO.getOperateType()) {
            case "0": // 业主或物业审批拒绝，发送访客
                // 所需跳转到的小程序appid（该小程序appid必须与发模板消息的公众号是绑定关联关系，暂不支持小游戏）
                miniprogramVisitor.put("appid",MINI_PROGRAM_APPID);
                // 所需跳转到小程序的具体页面路径，支持带参数,（示例index?foo=bar），要求该小程序已发布，暂不支持小游戏
                miniprogramVisitor.put("pagepath","pages/visitMore/visitMore?passId=" + weChatVisitorMsgDTO.getPassId() + "&msgStatus=0&projectId=" + visitorPassInfoMap.get("projectId").toString());
                paramsVisitor.put("miniprogram",miniprogramVisitor);
                keyword1Visitor.put("value","审批拒绝");   // 预约状态
                keyword1Visitor.put("color","#000000");
                dataVisitor.put("keyword1",keyword1Visitor);
                keyword4Visitor.put("value",visitorPassInfoMap.get("realName"));   // 被访人
                keyword4Visitor.put("color","#000000");
                dataVisitor.put("keyword4",keyword4Visitor);
                paramsVisitor.put("data",dataVisitor);
                LOG.info("发送访客模板消息参数：" + JSON.toJSONString(paramsVisitor));
                break;
            case "1": // 访客预约，提交访客单，发送访客和业主
                miniprogramVisitor.put("appid",MINI_PROGRAM_APPID);
                miniprogramVisitor.put("pagepath","pages/visitMore/visitMore?passId=" + weChatVisitorMsgDTO.getPassId() + "&msgStatus=1&projectId=" + visitorPassInfoMap.get("projectId").toString());
                paramsVisitor.put("miniprogram",miniprogramVisitor);
                miniprogramOwner.put("appid",MINI_PROGRAM_APPID);
                miniprogramOwner.put("pagepath","pages/visitMore/visitMore?passId=" + weChatVisitorMsgDTO.getPassId() + "&msgStatus=2&projectId=" + visitorPassInfoMap.get("projectId").toString());
                paramsOwner.put("miniprogram",miniprogramOwner);
                keyword1Visitor.put("value","待审批");   // 预约状态
                keyword1Visitor.put("color","#000000");
                dataVisitor.put("keyword1",keyword1Visitor);
                keyword1Owner.put("value","待审批");   // 预约状态
                keyword1Owner.put("color","#000000");
                dataOwner.put("keyword1",keyword1Owner);
                keyword4Visitor.put("value",visitorPassInfoMap.get("realName"));   // 被访人
                keyword4Visitor.put("color","#000000");
                dataVisitor.put("keyword4",keyword4Visitor);
                keyword4Owner.put("value",visitorPassInfoMap.get("visitorName"));   // 访客姓名
                keyword4Owner.put("color","#000000");
                dataOwner.put("keyword4",keyword4Owner);
                paramsVisitor.put("data",dataVisitor);
                paramsOwner.put("data",dataOwner);
                LOG.info("发送访客模板消息参数：" + JSON.toJSONString(paramsVisitor));
                LOG.info("发送业主模板消息参数：" + JSON.toJSONString(paramsOwner));
                break;
            case "2": // 业主审批通过，无需物业审核，发送访客
                miniprogramVisitor.put("appid",MINI_PROGRAM_APPID);
                miniprogramVisitor.put("pagepath","pages/visitTemporary/visitTemporary?passId=" + weChatVisitorMsgDTO.getPassId() + "&msgStatus=3&projectId=" + visitorPassInfoMap.get("projectId").toString());
                paramsVisitor.put("miniprogram",miniprogramVisitor);
                keyword1Visitor.put("value","通过");   // 预约状态
                keyword1Visitor.put("color","#000000");
                dataVisitor.put("keyword1",keyword1Visitor);
                keyword4Visitor.put("value",visitorPassInfoMap.get("realName"));   // 被访人
                keyword4Visitor.put("color","#000000");
                dataVisitor.put("keyword4",keyword4Visitor);
                paramsVisitor.put("data",dataVisitor);
                LOG.info("发送访客模板消息参数：" + JSON.toJSONString(paramsVisitor));
                break;
            case "3": // 业主审批通过，需要物业审核，发送访客
                miniprogramVisitor.put("appid",MINI_PROGRAM_APPID);
                miniprogramVisitor.put("pagepath","pages/visitTemporary/visitTemporary?passId=" + weChatVisitorMsgDTO.getPassId() + "&msgStatus=4&projectId=" + visitorPassInfoMap.get("projectId").toString());
                paramsVisitor.put("miniprogram",miniprogramVisitor);
                keyword1Visitor.put("value","请前往前台激活");   // 预约状态
                keyword1Visitor.put("color","#000000");
                dataVisitor.put("keyword1",keyword1Visitor);
                keyword4Visitor.put("value",visitorPassInfoMap.get("realName"));   // 被访人
                keyword4Visitor.put("color","#000000");
                dataVisitor.put("keyword4",keyword4Visitor);
                paramsVisitor.put("data",dataVisitor);
                LOG.info("发送访客模板消息参数：" + JSON.toJSONString(paramsVisitor));
                break;
            case "4": // 物业审批通过，发送访客和业主
                miniprogramVisitor.put("appid",MINI_PROGRAM_APPID);
                miniprogramVisitor.put("pagepath","pages/visitTemporary/visitTemporary?passId=" + weChatVisitorMsgDTO.getPassId() + "&msgStatus=5&projectId=" + visitorPassInfoMap.get("projectId").toString());
                paramsVisitor.put("miniprogram",miniprogramVisitor);
                miniprogramOwner.put("appid",MINI_PROGRAM_APPID);
                miniprogramOwner.put("pagepath","pages/visitTemporary/visitTemporary?passId=" + weChatVisitorMsgDTO.getPassId() + "&msgStatus=6&projectId=" + visitorPassInfoMap.get("projectId").toString());
                paramsOwner.put("miniprogram",miniprogramOwner);
                keyword1Visitor.put("value","通过");   // 预约状态
                keyword1Visitor.put("color","#000000");
                dataVisitor.put("keyword1",keyword1Visitor);
                keyword1Owner.put("value","访客到达");   // 预约状态
                keyword1Owner.put("color","#000000");
                dataOwner.put("keyword1",keyword1Owner);
                keyword4Visitor.put("value",visitorPassInfoMap.get("realName"));   // 被访人
                keyword4Visitor.put("color","#000000");
                dataVisitor.put("keyword4",keyword4Visitor);
                keyword4Owner.put("value",visitorPassInfoMap.get("visitorName"));   // 访客姓名
                keyword4Owner.put("color","#000000");
                dataOwner.put("keyword4",keyword4Owner);
                paramsVisitor.put("data",dataVisitor);
                paramsOwner.put("data",dataOwner);
                LOG.info("发送访客模板消息参数：" + JSON.toJSONString(paramsVisitor));
                LOG.info("发送业主模板消息参数：" + JSON.toJSONString(paramsOwner));
                break;
            default:
                return;
        }

        // 发送访客模板消息数据请求
        String sendResultVisitor = HttpProtocolUtil.httpPost(remoteUrl, JSON.toJSONString(paramsVisitor));
        LOG.info("发送访客模板消息返回数据：" + sendResultVisitor);
        try {
            Map<String, Object> result = JsonUtil.decode(sendResultVisitor, new TypeReference<Map<String, Object>>() {});
            // access_token无效，则重新获取再发一次，并更新缓存中无效的access_token
            if (result != null && result.get("errcode") != null && result.get("errcode").toString().equals("40001")) {
                String requestUrl = "https://api.weixin.qq.com/cgi-bin/token"+"?appid="+WECHAT_OFFICIAL_APPID+"&secret="+WECHAT_OFFICIAL_SECRET+"&grant_type=client_credential";
                JSONObject jsonObject = HttpProtocolUtil.httpsRequest(requestUrl, "GET", null);
                if (jsonObject != null) {
                    accessToken = jsonObject.getString("access_token");
                    if(StringUtils.isNotBlank(accessToken)){
                        redisService.set(RedisConstant.WECHAT_OFFICIAL_ACCESS_TOKEN,RedisConstant.WECHAT_OFFICIAL_TIME,accessToken);
                    }
                }
                remoteUrl = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" + accessToken;
                sendResultVisitor = HttpProtocolUtil.httpPost(remoteUrl, JSON.toJSONString(paramsVisitor));
                LOG.info("二次发送访客模板消息返回数据：" + sendResultVisitor);
                result = JsonUtil.decode(sendResultVisitor, new TypeReference<Map<String, Object>>() {});
            }
            if (result != null && result.get("errcode") != null && result.get("errcode").toString().equals("0")) {
                LOG.info("发送访客模板消息成功");
            } else {
                LOG.info("发送访客模板消息失败");
            }
        } catch (IOException e) {
            LOG.error("发送访客模板信息返回数据解析失败");
        }
        if ("1".equals(weChatVisitorMsgDTO.getOperateType()) || "4".equals(weChatVisitorMsgDTO.getOperateType())) {
            // 发送业主模板消息数据请求
            String sendResultOwner = HttpProtocolUtil.httpPost(remoteUrl, JSON.toJSONString(paramsOwner));
            LOG.info("发送业主模板消息返回数据：" + sendResultOwner);
            try {
                Map<String, Object> result = JsonUtil.decode(sendResultOwner, new TypeReference<Map<String, Object>>() {});
                if (result != null && result.get("errcode") != null && result.get("errcode").toString().equals("0")) {
                    LOG.info("发送业主模板消息成功");
                } else {
                    LOG.info("发送业主模板消息失败");
                }
            } catch (IOException e) {
                LOG.error("发送业主模板信息返回数据解析失败");
            }
        }
    }
}
